#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include "../../src/cli.h"
#include "../../src/conexion.h"
#include "../../src/utils.h"
#include <glib.h>
#include <glib/gprintf.h>
#include <gtk/gtk.h>

#define MS_ENTRE_TICKS 100


#define MAX_CANT_MENSAJES 10
#define MS_ENTRE_MENSAJES 1000



typedef struct {
	GtkWidget* ventana;
	GtkWidget* contenedor;
	GtkWidget* servidor;
	GtkWidget* puerto;
	GtkWidget* conectar;
	GtkWidget* desconectar;
	GtkWidget* log;
	int mensajes_enviados;
	gint tick_callback;
	char cerrar;
} t_ventana;




static void desconectar(t_ventana* v) {
	cli_desconectar();
	gtk_widget_set_sensitive(GTK_WIDGET(v->conectar), TRUE);
	gtk_widget_set_sensitive(GTK_WIDGET(v->desconectar), FALSE);
}

void imprimir_respuesta(int codigo, void* data, int size, void* objeto){
	if(codigo == CON_DATOS_RECIBIDOS) {
		t_ventana* v = (t_ventana*)objeto;
		GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(v->log));
		GtkTextMark *mark = gtk_text_buffer_get_insert (buffer);
		
		GtkTextIter iter;
		gtk_text_buffer_get_iter_at_mark (buffer, &iter, mark);
		gtk_text_buffer_insert (buffer, &iter, "\n", 1);
		gtk_text_buffer_insert (buffer, &iter, data, -1);
	}
}

void detectar_cierre(int codigo, void* data, int size, void* objeto) {
	if (codigo == CON_DESCONECTADO || codigo == CON_ERROR || codigo == CON_CERRADO) {
		t_ventana* v = (t_ventana*)objeto;
		printf("CLIENTE Cerrando sistema. Codigo recibido: '%s'.\n", conexion_describir_status(codigo));
		v->cerrar = 1;
	}
}

gint on_tick (gpointer data) {
	t_ventana* v = (t_ventana*)data;
	if (v->cerrar) {
		v->cerrar = 0;
		desconectar(v);
		return FALSE;
	}
	else {
		char mensaje[50];
		sprintf(mensaje, "msg.%d", v->mensajes_enviados++);
		printf("CLIENTE Enviando mensaje al servidor. Mensaje: '%s'\n", mensaje);
		cli_enviar(mensaje, strlen(mensaje)+1);
		cli_procesar();
		
		return TRUE;
	}
}

static void on_conectar_clicked(GtkWidget *widget, gpointer data) {
	t_ventana* v = (t_ventana*)data;
	v->cerrar = 0;
	v->mensajes_enviados = 0;
	cli_suscribir(imprimir_respuesta, v);
	cli_suscribir(detectar_cierre, v);
	
	char direccion[100];
	sprintf(direccion, "%s:%s", gtk_entry_get_text(GTK_ENTRY(v->servidor)),
								gtk_entry_get_text(GTK_ENTRY(v->puerto)));
	printf("Conectando con: %s\n", direccion);
	cli_conectar(direccion);
	
	v->tick_callback = g_timeout_add(MS_ENTRE_TICKS,on_tick, v);
	
	gtk_widget_set_sensitive(GTK_WIDGET(v->conectar), FALSE);
	gtk_widget_set_sensitive(GTK_WIDGET(v->desconectar), TRUE);
}

static void on_desconectar_clicked(GtkWidget *widget, gpointer data) {
	t_ventana* v = (t_ventana*)data;
	g_source_remove(v->tick_callback);
	v->tick_callback = 0;
	desconectar(v);
}

void ventana_init(t_ventana* v) {
	v->mensajes_enviados = 0;
	v->tick_callback = 0;
	v->cerrar = 0;
	
	v->ventana = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	
	gtk_container_set_border_width(GTK_CONTAINER(v->ventana), 10);
	
	v->contenedor = gtk_vbox_new(FALSE, 10);
	gtk_container_add(GTK_CONTAINER(v->ventana), v->contenedor);
	
	GtkWidget* contenedor_servidor = gtk_hbox_new(TRUE, 10);
	gtk_container_add(GTK_CONTAINER(v->contenedor), contenedor_servidor);
	GtkWidget* servidor_label = gtk_label_new("Servidor:");
	gtk_container_add(GTK_CONTAINER(contenedor_servidor), servidor_label);
	v->servidor = gtk_entry_new();
	gtk_container_add(GTK_CONTAINER(contenedor_servidor), v->servidor);
	
	GtkWidget* contenedor_puerto = gtk_hbox_new(TRUE, 10);
	gtk_container_add(GTK_CONTAINER(v->contenedor), contenedor_puerto);
	GtkWidget* puerto_label = gtk_label_new("Puerto:");
	gtk_container_add(GTK_CONTAINER(contenedor_puerto), puerto_label);
	v->puerto = gtk_entry_new();
	gtk_container_add(GTK_CONTAINER(contenedor_puerto), v->puerto);
	
	v->log = gtk_text_view_new();
	gtk_container_add(GTK_CONTAINER(v->contenedor), v->log);
	
	v->conectar = gtk_button_new_with_label("Conectar");
	g_signal_connect(G_OBJECT(v->conectar), "clicked", G_CALLBACK(on_conectar_clicked),
					 v);
	gtk_container_add(GTK_CONTAINER(v->contenedor), v->conectar);
	
	v->desconectar = gtk_button_new_with_label("Desconectar");
	g_signal_connect(G_OBJECT(v->desconectar), "clicked", G_CALLBACK(on_desconectar_clicked),
					 v);
	gtk_container_add(GTK_CONTAINER(v->contenedor), GTK_WIDGET(v->desconectar));
}

void ventana_on_destroy(t_ventana* v, void (*destroy_callback)(GtkWidget *widget, gpointer data)) {
	g_signal_connect(G_OBJECT(v->ventana), "destroy", G_CALLBACK(destroy_callback),
					 NULL);
}

void ventana_show(t_ventana* v) {
	gtk_widget_show_all(v->ventana);
}

void ventana_destroy(t_ventana* v) {
	if (v->tick_callback)
		g_source_remove(v->tick_callback);
	gtk_widget_show_all(v->ventana);
}

static void destruir(GtkWidget *widget, gpointer data)
{
	gtk_main_quit();
}

int main(int argc, char *argv[]) {
	
	gtk_init(&argc, &argv);
	cli_iniciar();
	
	t_ventana ventana;
	ventana_init(&ventana);
	ventana_on_destroy(&ventana, destruir);
	ventana_show(&ventana);
	gtk_main();
	ventana_destroy(&ventana);
	cli_terminar();
	return 0;
}
